<template>
  <section class="search-bar art-custom-card">
    <ElForm 
      ref="fieldFormRef" 
      :model="formData" 
      :rules="fieldRules" 
      :label-width="props.labelWidth"
      class="dynamic-form"
    >
      <template v-for="(row, rowIndex) in computedRows" :key="rowIndex">
        <ElRow :gutter="20">
          <ElCol 
            v-for="col in row" 
            :key="col.name"
			:xs="24"
			:sm="12"
			:md="12"
			:lg="col.span || 12"
			:xl="col.span || 12"
          >
            <ElFormItem 
              v-if="shouldShowField(col)"
              :label="col.label" 
              :prop="col.name"
              :rules="col.rules"
            >
              <component
                :is="fieldComponents[col.controlType]"
                v-if="fieldComponents[col.controlType]"
                :field="col"
                :data="formData"
                :fetchOptions="props.fetchDatas[col.name]"
                :option="props.options[col.name]"
              />
            </ElFormItem>
          </ElCol>
		  
		  <ElCol 
		  :xs="24"
		  :sm="12"
		  :md="12 "
		  :lg="btnSpan  || 12 "
		  :xl="btnSpan  || 12 " 
		  
		  class="action-column" v-if="rowIndex+1 ==computedRows.length">
		    <div class="action-buttons-wrapper">
		      <div class="form-buttons">
		        <el-button class="reset-button" @click="handleReset" v-ripple>
		          {{ $t('table.searchBar.reset') }}
		        </el-button>
		        <el-button type="primary" class="search-button" @click="handleSearch" v-ripple>
		          {{ $t('table.searchBar.search') }}
		        </el-button>
		      </div>
		      
		      <div
		        v-if="!props.isExpand && props.showExpand"
		        class="filter-toggle"
		        @click="isShow = !isShow"
		      >
		        <span>
		          {{ isShow ? $t('table.searchBar.collapse') : $t('table.searchBar.expand') }}
		        </span>
		        <div class="icon-wrapper">
		          <el-icon>
		            <ArrowUpBold v-if="isShow" />
		            <ArrowDownBold v-else />
		          </el-icon>
		        </div>
		      </div>
		    </div>
		  </ElCol>
        </ElRow>
      </template>
    </ElForm>
  </section>
</template>

<script setup lang="ts">
import { 
  FormRules, 
  FormInstance, 
  FormItemRule,
  type ComponentSize 
} from 'element-plus'
import { ref, reactive, watch, computed, onMounted } from 'vue'
import { ArrowUpBold, ArrowDownBold } from '@element-plus/icons-vue'
import { PropType } from 'vue-demi'
import { useWindowSize } from '@vueuse/core'
import { RuleService } from '@/api/data-rule/ruleApi'
import { DictService } from '@/api/sys/dictApi'
import { number } from 'echarts'

// 动态导入所有字段组件
const fieldComponents = {
  Input: defineAsyncComponent(() => import('./fields/InputField.vue')),
  Textarea: defineAsyncComponent(() => import('./fields/InputField.vue')),
  Password: defineAsyncComponent(() => import('./fields/InputField.vue')),
  Select: defineAsyncComponent(() => import('./fields/SelectField.vue')),
  TreeSelect: defineAsyncComponent(() => import('./fields/TreeSelectField.vue')),
  Switch: defineAsyncComponent(() => import('./fields/SwitchField.vue')),
  Radio: defineAsyncComponent(() => import('./fields/RadioGroupField.vue')),
  Checkbox: defineAsyncComponent(() => import('./fields/CheckboxGroupField.vue')),
  InputNumber: defineAsyncComponent(() => import('./fields/InputNumberField.vue')),
  Slider: defineAsyncComponent(() => import('./fields/SliderField.vue')),
  Rate: defineAsyncComponent(() => import('./fields/RateField.vue')),
  DatePicker: defineAsyncComponent(() => import('./fields/DatePickerField.vue')),
  TimePicker: defineAsyncComponent(() => import('./fields/TimePickerField.vue')),
  DateTimePicker: defineAsyncComponent(() => import('./fields/DateTimePickerField.vue')),
  ColorPicker: defineAsyncComponent(() => import('./fields/ColorPickerField.vue'))
}

// 类型定义
type FetchFunction = (params?: any) => Promise<any>;
type FetchDataHandler = (value: any, row: Record<string, any>, fetchFunc: FetchFunction) => any;
type FetchDatasType = Record<string, FetchDataHandler>;
type FieldConfig = {
  name: string;
  label: string;
  controlType: string;
  span?: number;
  isVisible?: string;
  isNullable?: string;
  min?: number;
  max?: number;
  pattern?: string;
  validator?: (value: any) => boolean;
  defaultValue?: any;
  isArray?: string;
  width?:number;
  rules?: FormItemRule[];
};

const { width } = useWindowSize();
const isMobile = computed(() => width.value < 500);

const emit = defineEmits(['init:completed', 'reset', 'search']);

const props = defineProps({
  rule: {
    type: String,
    required: true
  },
  columnData: {
    type: Object as PropType<Record<string, any>>,
    default: () => ({})
  },
  fetchData: {
    type: Function as PropType<(params?: any) => Promise<any>>,
    required: false
  },
  autoLoad: {
    type: Boolean,
    default: true
  },
  isExpand: {
    type: Boolean,
    default: false
  },
  showExpand: {
    type: Boolean,
    default: true
  },
  labelWidth: {
    type: String,
    default: '70px'
  },
  data: {
    type: Object as PropType<Record<string, any>>,
    default: () => ({})
  },
  customFormatters: {
    type: Object as PropType<Record<string, (value: any, row: any) => any>>,
    default: () => ({})
  },
  fetchDatas: {
    type: Object as PropType<FetchDatasType>,
    default: () => ({}),
    validator: (value: FetchDatasType) => {
      return Object.values(value).every(fn => typeof fn === 'function');
    }
  },
  options: {
    type: Object as PropType<Record<string, any>>,
    default: () => ({})
  },
  preview: {
    type: Boolean,
    default: false
  }
});

// 响应式数据
const formData = ref<Record<string, any>>({});
const fieldFormRef = ref<FormInstance>();
const columnConfigs = ref<FieldConfig[]>([]);
const loading = ref(false);
const isShow = ref(false);
const fieldRules = reactive<FormRules>({});
const btnSpan = ref<number>(0);

// 计算属性
const computedRows = computed(() => {
  const rows: FieldConfig[][] = [];
  const isshowLess = !props.isExpand && !isShow.value;

  if (isshowLess) {
    // 折叠状态：只返回一行，确保 span 总和 + btnSpan = 24
    const visibleConfigs = columnConfigs.value.filter(config => shouldShowField(config));
    let spanSum = 0;
    const limitedRow: FieldConfig[] = [];

    for (const config of visibleConfigs) {
      const span = config.span || 12;
      if (spanSum + span + 5 <= 24) {
        limitedRow.push(config);
        spanSum += span;
      } else {
        break;
      }
    }
    btnSpan.value = 24 - spanSum; // 按钮占剩余空间
    return [limitedRow];
  } else {
    // 展开状态：正常分组，计算 btnSpan
    let currentRow: FieldConfig[] = [];
    let currentSpan = 0;
    let totalSpanSum = 0; // 所有行的 span 总和（用于判断是否所有行都刚好 24）
    let isAllRowsFull = true; // 是否所有行都刚好填满 24

    for (const config of columnConfigs.value) {
      if (!shouldShowField(config)) continue;
      
      const span = config.span || 12;
      totalSpanSum += span;
      
      if (span === 24) {
        if (currentRow.length > 0) {
          rows.push([...currentRow]);
          currentRow = [];
          currentSpan = 0;
        }
        rows.push([config]);
        continue;
      }
    
      if (currentSpan + span > 24) {
        if (currentSpan !== 24) isAllRowsFull = false; // 当前行未填满 24
        rows.push([...currentRow]);
        currentRow = [config];
        currentSpan = span;
      } else {
        currentRow.push(config);
        currentSpan += span;
      }
    }
    
    if (currentRow.length > 0) {
      if (currentSpan !== 24) isAllRowsFull = false; // 最后一行未填满 24
      rows.push(currentRow);
    }
    
    // 展开状态下：
    // - 如果所有行刚好 24，则 btnSpan = 24（按钮单独一行）
    // - 否则，btnSpan = 24 - 最后一行的剩余空间
    btnSpan.value = isAllRowsFull ? 24 : (24 - currentSpan);
    return rows;
  }
});

// 方法
const shouldShowField = (col: FieldConfig) => {
  return col.isVisible === '0';
};

const initFormRules = () => {
  Object.keys(fieldRules).forEach(key => delete fieldRules[key]);
  
  columnConfigs.value.forEach(config => {
    const rules: FormItemRule[] = [];
    
    if (config.isNullable === '1') {
      rules.push({
        required: true,
        message: `${config.label}不能为空`,
        trigger: ['blur', 'change']
      });
    }

    if ((config.max !== config.min) && ['Textarea','Input'].includes(config.controlType)) {
      rules.push({
        min: config.min ? Number(config.min) : 0,
        max: config.max ? Number(config.max) : undefined,
        message: `${config.label}长度需在${config.min || 0}-${config.max}之间`,
        trigger: 'blur'
      });
    }

    if (config.pattern) {
      rules.push({
        pattern: new RegExp(config.pattern),
        message: `${config.label}格式不正确`,
        trigger: 'blur'
      });
    }

    if (config.validator) {
      rules.push({
        validator: (_, value) => {
          if (typeof config.validator === 'function') {
            return config.validator(value);
          }
          return true;
        },
        trigger: 'blur'
      });
    }

    if (rules.length > 0) {
      fieldRules[config.name] = rules;
    }
  });
};

const initFormData = () => {
  const initialData: Record<string, any> = {};
  columnConfigs.value.forEach(config => {
    if (config.isArray === '1') {
      const values = new Set<any>();
      if (config.defaultValue && config.defaultValue !== undefined) {
        config.defaultValue.split(',').forEach((item: any) => {
          values.add(item.trim());
        });
      }
      initialData[config.name] = Array.from(values);
    } else {
      initialData[config.name] = config.defaultValue !== undefined ? config.defaultValue : undefined;
    }
  });
  
  formData.value = { ...initialData, ...props.columnData };
};

const loadData = async (params?: any) => {
  if (!props.fetchData) return;
  
  loading.value = true;
  try {
    const data = await props.fetchData(params);
    if (data && Object.keys(data).length > 0) {
      formData.value = { ...formData.value, ...data };
    }
  } catch (error) {
    console.error('数据加载失败', error);
  } finally {
    loading.value = false;
  }
};

const fetchColumns = async () => {
  try {
    const { fields } = await RuleService.getColumns(props.rule);
    columnConfigs.value = fields;
    initFormRules();
    initFormData();
    emit('init:completed', formData.value);
  } catch (error) {
    console.error('列配置加载失败', error);
  }
};

const handleReset = () => {
  if (fieldFormRef.value) {
    fieldFormRef.value.resetFields();
    initFormData();
  }
  emit('reset');
};

const handleSearch = () => {
  fieldFormRef.value?.validate((valid) => {
    if (valid) {
      emit('search', formData.value);
    }
  });
};

// 生命周期
onMounted(async () => {
  await fetchColumns();
  if (props.autoLoad && props.fetchData) {
    await loadData();
  } else if (props.data) {
    formData.value = { ...formData.value, ...props.data };
  }
});

// 监听器
watch(() => props.columnData, (newVal) => {
  formData.value = { ...formData.value, ...newVal };
}, { deep: true });

watch(() => props.data, (newVal) => {
  formData.value = { ...formData.value, ...newVal };
}, { deep: true });

// 暴露方法
defineExpose({
  validate: () => fieldFormRef.value?.validate(),
  getFormData: () => formData.value,
  resetForm: ()=> handleReset,
  updateField: (prop: string, value: any) => {
    if (prop in formData.value) {
      formData.value[prop] = value;
    }
  }
});
</script>

<style scoped lang="scss">
.search-bar {
  padding: 20px 20px 0;
  background-color: var(--art-main-bg-color);
  border-radius: calc(var(--custom-radius) / 2 + 2px);

  :deep(.el-form-item__label) {
    display: flex;
    align-items: center;
    line-height: 20px;
  }

  .action-buttons-wrapper {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-start;
    margin-bottom: 12px;
    padding-right: 12px;
    
    .form-buttons {
      margin-right: 16px;
    }

    .filter-toggle {
      display: flex;
      align-items: center;
      line-height: 32px;
      color: var(--main-color);
      cursor: pointer;
      user-select: none;

      span {
        font-size: 14px;
      }

      .icon-wrapper {
        display: flex;
        align-items: center;
        margin-left: 4px;
        font-size: 14px;
      }
    }
  }

  @media (max-width: 768px) {
    padding: 16px 12px 0;
    
    .action-buttons-wrapper {
      justify-content: space-between;
      
      .form-buttons {
        margin-right: 0;
      }
    }
  }
}
</style>